package mume.infoRetriever;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

public class AsinInfoRetriever {
	
	private boolean infoRetrieved;
	
	private AsinInfoHandler asinHandler;
	private TrackListHandler trackListHandler;
	private ArtistInfoHandler artistInfoHandler;
	private AlbumInfoHandler albumInfoHandler;
	private String debug = "";
	
	private boolean error;
	
	private static String LAST_FM_API = "c71d2d4615467f0cf6d624ee5c5660c0";
	
	public AsinInfoRetriever(){
		infoRetrieved = false;
		error = false;
		
		asinHandler = new AsinInfoHandler();
		trackListHandler = new TrackListHandler();
		artistInfoHandler = new ArtistInfoHandler();
		albumInfoHandler = new AlbumInfoHandler();
	}
	
	public void retrieveInfo(String asin){
		if(!error)
			ProcessAsin(asin);
		if(!error)
			GetArtistInfo(asinHandler.getArtistId());
		if(!error)
			GetAlbumInfo(asinHandler.getAlbum(), asinHandler.getArtist());
		if(!error)
			ProcessTrackList(asinHandler.getAlbumId());
		if(error) {
			infoRetrieved = false;
			error = false;
		} else
			infoRetrieved = true;
	}
	public String getArtist(){
		if(infoRetrieved)
			return asinHandler.getArtist();
		else
			return "no asin loaded";
	}
	
	public String getAlbum(){
		if(infoRetrieved)
			return asinHandler.getAlbum();
		else
			return "no asin loaded";
	}
	
	public String getArtistInfo(){
		if(infoRetrieved)
			return artistInfoHandler.getArtistInfo();
		else
			return "no asin loaded";
	}

	public String getArtistImage(){
		if(infoRetrieved)
			return artistInfoHandler.getImage();
		else
			return "no asin loaded";
	}
	
	public String getAlbumInfo(){
		if(infoRetrieved)
			return albumInfoHandler.getAlbumInfo();
		else
			return "no asin loaded";
	}

	public String getAlbumImage(){
		if(infoRetrieved)
			return albumInfoHandler.getImage();
		else
			return "no asin loaded";
	}
	
	public List<String> getTrackList(){
		if(infoRetrieved)
			return trackListHandler.getTracks();
		else
			return new ArrayList<String>();
	}
	
	public int getNumberOfTracks(){
		if(infoRetrieved)
			return trackListHandler.getNoOfTracks();
		else
			return 0;
	}
	
	private String createFullUrl(String url, Map<String,String> params){
    	String result = url;
    	result = result.concat("?");
    	Iterator<Entry<String, String>> it = params.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String,String> pairs = (Map.Entry<String,String>)it.next();
            result = result.concat(pairs.getKey() + "=" + pairs.getValue());
            if(it.hasNext())
            	result = result.concat("&");
        }
        result = result.replace(" ", "%20");
    	return result;
    }

	private void retrieveData(String url, Map<String,String> params, DefaultHandler handler){
		try {
	        URI uri = new URI(createFullUrl(url, params));
			DefaultHttpClient client = new DefaultHttpClient();
		
			HttpGet method = new HttpGet(uri);
			HttpResponse res = client.execute(method);
			
			SAXParserFactory spf = SAXParserFactory.newInstance();
			SAXParser sp = spf.newSAXParser();
			XMLReader xr = sp.getXMLReader();
			xr.setContentHandler(handler);	
			xr.setErrorHandler(handler);

			xr.parse(new InputSource(res.getEntity().getContent()));
						
		} catch (ClientProtocolException e) {
			e.printStackTrace();
			debug = debug + "client ex" + e.getMessage();
			error = true;
		} catch (IOException e) {
			e.printStackTrace();
			debug = debug + "io ex" + e.getMessage();
			error = true;
		} catch (URISyntaxException e) {
			e.printStackTrace();
			debug = debug + "uri ex" + e.getMessage();
			error = true;
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
			debug = debug + "parser ex" + e.getMessage();
			error = true;
		} catch (SAXException e) {
			e.printStackTrace();
			debug = debug + "sax ex" + e.getMessage();
			error = true;
		}
	}
	
    private void ProcessAsin(String asin) {
        String url = "http://musicbrainz.org/ws/1/release/";
        
        Map<String,String> params = new HashMap<String,String>();
        params.put("type", "xml");
        params.put("asin", asin);
        
        retrieveData(url, params, asinHandler);
	}
    private void ProcessTrackList(String albumId) {
    	String url = "http://musicbrainz.org/ws/1/track/";

		Map<String,String> params = new HashMap<String,String>();
        params.put("type", "xml");
        params.put("releaseid", albumId);
        
        retrieveData(url, params, trackListHandler);
    }
    private void GetArtistInfo(String artistId) {
    	String url = "http://ws.audioscrobbler.com/2.0/";

		Map<String,String> params = new HashMap<String,String>();
        params.put("method", "artist.getinfo");
        params.put("mbid", artistId);
        params.put("api_key", LAST_FM_API);
        
        retrieveData(url, params, artistInfoHandler);
    }
    
    private void GetAlbumInfo(String albumName, String artistName) {
    	String url = "http://ws.audioscrobbler.com/2.0/";
		Map<String,String> params = new HashMap<String,String>();
        params.put("method", "album.getinfo");
        params.put("album", albumName);
        params.put("artist", artistName);
        params.put("api_key", LAST_FM_API);
        
        retrieveData(url, params, albumInfoHandler);
    }
    
    public String InfoToString() {
    	return albumInfoHandler.toString() + "\n"
    		+ artistInfoHandler.toString() + "\n"
    		+ asinHandler.toString() + "\n" 
    		+ trackListHandler.toString() + "\n"
    	 	+ "debug: " + debug;
    }
}
